# !/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time        : 2021/10/20 17:39
@Author      : Albert Darren
@Contact     : 2563491540@qq.com
@File        : breast_cancer_classification.py
@Version     : Version 1.0.0
@Description : TODO
@Created By  : PyCharm
"""
from sklearn.model_selection import train_test_split


def train(x_train, y_train, criterion="gini"):
    """
    返回使用训练集训练后的模型
    :param x_train: 训练集特征
    :param y_train: 训练集标记
    :param criterion: 最优属性划分原则，默认基尼指数
    :return: 模型
    """
    from sklearn import tree
    # 决策树生成和训练
    classifier = tree.DecisionTreeClassifier(criterion=criterion)
    classifier.fit(x_train, y_train)
    return classifier


def test(model, x_test, y_test):
    """
    返回模型在测试集上的精度
    :param model: 模型
    :param x_test: 测试集特征
    :param y_test: 测试集标记
    :return: 精度
    """
    # 预测结果
    y_pred = model.predict(x_test)
    # 模型评价
    acc_num = 0
    for pre_y, y in zip(y_pred, y_test):
        if pre_y == y:
            acc_num += 1
    return acc_num / len(y_test)


def repeat(data, target, test_size=0.2, count=100, criterion="gini", accuracy_type="median"):
    """
    返回重复指定次数精度的中值或者均值
    :param data:数据集特征
    :param target:数据集标记
    :param test_size: 测试集比例，默认0.2
    :param count: 指定次数
    :param criterion: 最优属性划分原则，默认基尼指数
    :param accuracy_type: 精度类型
    :return: 精度中值或者均值
    """
    import numpy as np
    accuracy_array = np.zeros(count)
    for loop in range(count):
        x_train, x_test, y_train, y_test = train_test_split(data, target, test_size=test_size)
        decision_tree = train(x_train, y_train, criterion=criterion)
        accuracy_array[loop] = test(decision_tree, x_test, y_test)
    if accuracy_type == "median":
        return np.median(accuracy_array)
    elif accuracy_type == "mean":
        return np.mean(accuracy_array)


if __name__ == '__main__':
    from pandas import read_csv
    from numpy import array

    data_path = "../dataset/BreastTissue.csv"
    wine_df = read_csv(data_path, header=0, names=list(range(1, 11)))
    x = array(wine_df.iloc[:, 1:])
    y = array(wine_df.iloc[:, 0])
    median_accuracy = repeat(x, y)
    print("基尼指数最优属性划分测试集精度中值:{0:.2f}%".format(median_accuracy * 100))
    mean_accuracy = repeat(x, y, accuracy_type="mean")
    print("基尼指数最优属性划分测试集精度均值:{0:.2f}%".format(mean_accuracy * 100))
    median_accuracy = repeat(x, y, criterion="entropy")
    print("香农熵最优属性划分测试集精度中值:{0:.2f}%".format(median_accuracy * 100))
    mean_accuracy = repeat(x, y, accuracy_type="mean", criterion="entropy")
    print("香农熵最优属性划分测试集精度均值:{0:.2f}%".format(mean_accuracy * 100))
